/*
 * @Author: liuqiang
 * @Date: 2021-10-01 17:53:42
 * @LastEditTime: 2021-10-02 00:10:13
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \练习\snake\src\moduls\GameControl.ts
 */

import Snake from "./Snake"
import ScorePanel from "./ScorePanel"
import Food from "./Food"

// 游戏控制器, 控制其他的所有类
class GameControl {
  // 定义三个属性 蛇 食物 计分器
  snake: Snake;
  food: Food;
  scorePanel: ScorePanel;
  // 创建一个属性来存储蛇的移动方向(蛇的移动方向)
  derection: string = 'Right'
  // 创建一个属性 记录游戏是否结束
  isLive: boolean = true

  constructor() {
    this.snake = new Snake()
    this.food = new Food()
    this.scorePanel = new ScorePanel()

    this.init()
  }

  // 初始化游戏
  init() {
    // 绑定键盘事件 bind(this) 改变this指向,否至this将指向document而不是GameControl这个类
    document.addEventListener('keydown', this.keyDownHandler)
    // 调用run方法
    this.run()
  }

  // 键盘按下的响应函数
  keyDownHandler = (event: KeyboardEvent) => {
    // event.key的值 IE下是后面的值
    // ArrowUp || Up
    // ArrowLeft || Left
    // ArrowRight || Right
    // ArrowDown || Down
    this.derection = event.key
  }

  // 创建蛇移动的方案
  run() {
    /**
     * 根据this.derection来使蛇的位置改变
     * 向上 top 减少
     * 向下 top 增加
     * 向右 left 增加
     * 向左 left 减少
     */    
    let X = this.snake.X
    let Y= this.snake.Y

    // 根据按键方向修改X,Y
    switch (this.derection) {
      case "ArrowUp":
      case "Up":
        Y -= 10
        break;

      case "ArrowDown":
      case "Down":
        Y += 10
        break;
      
      case "ArrowLeft":
      case "Left":
        X -= 10
        break;

      case "ArrowRight":
      case "Right":
        X += 10
        break;
    }

    // 检查蛇是否吃到食物
    this.checkEat(X, Y)

    // 修改蛇的X,Y
    try {
      this.snake.X = X
      this.snake.Y = Y
    } catch (error) {
      // 进入catch,游戏结素
      alert('Game Over')
      this.isLive = false
    }
    
    // 开启一个定时调用
    this.isLive && setTimeout(() => {
      this.run()
    }, 300 - (this.scorePanel.level) * 30);

  }

  // 定义一个方法,用来检查蛇是否吃到食物
  checkEat(X: number, Y: number) {
    if(X === this.food.X && Y === this.food.Y) {
      this.food.change() // 改变食物位置
      this.scorePanel.addScore() // 加分
      this.snake.addBody() // 增加蛇长度
    }
  }
}

export default GameControl
